home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagg_m.zip / MATH.SWG / 0039_Expression Evaluator.pas < prev    next >
Pascal/Delphi Source File  |  1993-11-02  |  6KB  |  202 lines

  1. {
  2. THAI TRAN
  3.  
  4. {
  5. I've netmailed you the full-featured version (800 lines!) that will do
  6. Functions, exponentiation, factorials, and has all the bells and whistles,
  7. but I thought you might want to take a look at a simple version so you can
  8. understand the algorithm.
  9.  
  10. This one only works With +, -, *, /, (, and ).  I wrote it quickly, so it
  11. makes extensive use of global Variables and has no error checking; Use at
  12. your own risk.
  13.  
  14. Algorithm to convert infix to postfix (RPN) notation
  15. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  16. Parse through the entire expression getting each token (number, arithmetic
  17. operator, left or right parenthesis).  For each token, if it is:
  18.  1. an operand (number)        Send it to the RPN calculator
  19.  2. a left parenthesis         Push it onto the operator stack
  20.  3. a right parenthesis        Pop operators off stack and send to RPN
  21.                                calculator Until the a left parenthesis is
  22.                                on top of the stack.  Pop it also, but don't
  23.                                send it to the calculator.
  24.  4. an operator                While the stack is not empty, pop operators
  25.                                off the stack and send them to the RPN
  26.                                calculator Until you reach one With a higher
  27.                                precedence than the current operator (Note:
  28.                                a left parenthesis has the least precendence).
  29.                                Then push the current operator onto the stack.
  30.  
  31. This will convert (4+5)*6/(2-3) to 4 5 + 6 * 2 3 - /
  32.  
  33. Algorithm For RPN calculator
  34. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  35. Note:  this Uses a different stack from the one described above.
  36.  
  37. In RPN, if an operand (a number) is entered, it is just pushed onto the
  38. stack.  For binary arithmetic operators (+, -, *, /, and ^), the top two
  39. operands are popped off the stack, operated on, and the result pushed back
  40. onto the stack.  if everything has gone correctly, at the end, the answer
  41. should be at the top of the stack.
  42.  
  43.  
  44. Released to Public Domain by Thai Tran (if that matters).
  45. }
  46.  
  47. {$X+}
  48. Program Expression_Evaluator;
  49.  
  50. Const
  51.   RPNMax = 10;              { I think you only need 4, but just to be safe }
  52.   OpMax  = 25;
  53.  
  54. Type
  55.   String15 = String[15];
  56.  
  57. Var
  58.   Expression : String;
  59.   RPNStack   : Array[1..RPNMax] of Real;        { Stack For RPN calculator }
  60.   RPNTop     : Integer;
  61.   OpStack    : Array[1..OpMax] of Char;    { Operator stack For conversion }
  62.   OpTop      : Integer;
  63.  
  64. Procedure RPNPush(Num : Real); { Add an operand to the top of the RPN stack }
  65. begin
  66.   if RPNTop < RPNMax then
  67.   begin
  68.     Inc(RPNTop);
  69.     RPNStack[RPNTop] := Num;
  70.   end
  71.   else  { Put some error handler here }
  72. end;
  73.  
  74. Function RPNPop : Real;       { Get the operand at the top of the RPN stack }
  75. begin
  76.   if RPNTop > 0 then
  77.   begin
  78.     RPNPop := RPNStack[RPNTop];
  79.     Dec(RPNTop);
  80.   end
  81.   else  { Put some error handler here }
  82. end;
  83.  
  84. Procedure RPNCalc(Token : String15);                       { RPN Calculator }
  85. Var
  86.   Temp  : Real;
  87.   Error : Integer;
  88. begin
  89.   Write(Token, ' ');                { This just outputs the RPN expression }
  90.  
  91.   if (Length(Token) = 1) and (Token[1] in ['+', '-', '*', '/']) then
  92.   Case Token[1] of                                   { Handle operators }
  93.     '+' : RPNPush(RPNPop + RPNPop);
  94.     '-' : RPNPush(-(RPNPop - RPNPop));
  95.     '*' : RPNPush(RPNPop * RPNPop);
  96.     '/' :
  97.     begin
  98.       Temp := RPNPop;
  99.       if Temp <> 0 then
  100.         RPNPush(RPNPop/Temp)
  101.       else  { Handle divide by 0 error }
  102.     end;
  103.   end
  104.   else
  105.   begin                   { Convert String to number and add to stack }
  106.     Val(Token, Temp, Error);
  107.     if Error = 0 then
  108.       RPNPush(Temp)
  109.     else  { Handle error }
  110.   end;
  111. end;
  112.  
  113. Procedure OpPush(Operator : Char);  { Add an operator onto top of the stack }
  114. begin
  115.   if OpTop < OpMax then
  116.   begin
  117.     Inc(OpTop);
  118.     OpStack[OpTop] := Operator;
  119.   end
  120.   else  { Put some error handler here }
  121. end;
  122.  
  123. Function OpPop : Char;               { Get operator at the top of the stack }
  124. begin
  125.   if OpTop > 0 then
  126.   begin
  127.     OpPop := OpStack[OpTop];
  128.     Dec(OpTop);
  129.   end
  130.   else  { Put some error handler here }
  131. end;
  132.  
  133. Function Priority(Operator : Char) : Integer; { Return priority of operator }
  134. begin
  135.   Case Operator OF
  136.     '('      : Priority := 0;
  137.     '+', '-' : Priority := 1;
  138.     '*', '/' : Priority := 2;
  139.     else  { More error handling }
  140.   end;
  141. end;
  142.  
  143. Procedure Evaluate(Expr : String);                                  { Guess }
  144. Var
  145.   I     : Integer;
  146.   Token : String15;
  147. begin
  148.   OpTop  := 0;                                              { Reset stacks }
  149.   RPNTop := 0;
  150.   Token  := '';
  151.  
  152.   For I := 1 to Length(Expr) DO
  153.   if Expr[I] in ['0'..'9'] then
  154.   begin       { Build multi-digit numbers }
  155.     Token := Token + Expr[I];
  156.     if I = Length(Expr) then          { Send last one to calculator }
  157.       RPNCalc(Token);
  158.   end
  159.   else
  160.   if Expr[I] in ['+', '-', '*', '/', '(', ')'] then
  161.   begin
  162.     if Token <> '' then
  163.     begin        { Send last built number to calc. }
  164.       RPNCalc(Token);
  165.       Token := '';
  166.     end;
  167.  
  168.     Case Expr[I] OF
  169.       '(' : OpPush('(');
  170.       ')' :
  171.       begin
  172.         While OpStack[OpTop] <> '(' DO
  173.           RPNCalc(OpPop);
  174.         OpPop;                          { Pop off and ignore the '(' }
  175.       end;
  176.  
  177.       '+', '-', '*', '/' :
  178.       begin
  179.         While (OpTop > 0) AND
  180.               (Priority(Expr[I]) <= Priority(OpStack[OpTop])) DO
  181.           RPNCalc(OpPop);
  182.         OpPush(Expr[I]);
  183.       end;
  184.     end; { Case }
  185.   end
  186.   else;
  187.       { Handle bad input error }
  188.  
  189.   While OpTop > 0 do                     { Pop off the remaining operators }
  190.     RPNCalc(OpPop);
  191. end;
  192.  
  193. begin
  194.   Write('Enter expression: ');
  195.   Readln(Expression);
  196.  
  197.   Write('RPN Expression = ');
  198.   Evaluate(Expression);
  199.   Writeln;
  200.   Writeln('Answer = ', RPNPop : 0 : 4);
  201. end.
  202.